package dslProgramGen.dslStatement;

import dslProgramGen.DslProgramGen;
import dslProgramGen.WhoPointToThisObjectCollection;
import utils.Utils;

import java.util.List;
import java.util.Map;

import static dslProgramGen.util.DslProgramGenUtil.*;

public class DslStatement {

    /**
     * 处理Put trace语句 赋值给A.field trace转DSL
     * 生成 A.field = dslStatement; DSL语句
     * field可能为静态字段也可能为实例字段
     *
     * @param putTraceLine            put操作所在的Trace行
     * @param isStatic                字段是否为静态字段
     * @param dslMethodContentList    生成的DSL程序的函数体
     * @param objId2objExpressionsMap 指定对象id在DSL程序中可以怎样表示出来 <objId, expressions>
     * @param dslObjFieldToObjIdMap   给定DSL语句（对象.field 或 对象数组[index]），看看该DSL语句指向哪个对象Id，主要是帮助处理Put与PutA的trace，减少查询时间
     */
    public static void genDslStatementAssignToObjField(String putTraceLine,
                                                       boolean isStatic,
                                                       List<String> dslMethodContentList,
                                                       Map<String, WhoPointToThisObjectCollection> objId2objExpressionsMap,
                                                       Map<String, String> dslObjFieldToObjIdMap) {
        // 修改静态字段例子 Put H1:0x0000000046cdf8bd, C1:Student, IS:true, H2:0x000000000f0c8a99, C2:Course, F:112, T:main, M:java/lang/module/Configuration.<init> (Ljava/util/List;Ljava/lang/module/Resolver;)V
        // 修改实例字段例子 Put H1:0x000000003de64145, C1:java/lang/module/Configuration, IS:false, H2:0x000000001ecd979e, C2:java/util/ImmutableCollections$List12, F:12, T:main, M:java/lang/module/Configuration.<init> (Ljava/util/List;Ljava/lang/module/Resolver;)V
        String leftStatement;
        String h2ObjId;
        if (isStatic) {
            // 修改的是静态字段
            // 生成DSL语句，例如 Student.field = dslStatement;
            // 获得C1的类名称
            String c1ClassName = Utils.RegularExpressionProcess(putTraceLine, "C1:(.*?),");
            c1ClassName = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(c1ClassName);
            // 获得修改C1的字段名
            String fieldName = Utils.RegularExpressionProcess(putTraceLine, "F:(.*?),");
            // 获得H2的id
            h2ObjId = Utils.RegularExpressionProcess(putTraceLine, "H2:(.*?),");
            // 判断 H2是否为NULL
            // 修改静态字段例子 Put H1:0x0000000046cdf8bd, C1:Student, IS:true, H2:NULL, C2:NULL, F:112, T:main, M:java/lang/module/Configuration.<init> (Ljava/util/List;Ljava/lang/module/Resolver;)V
            if ("NULL".equals(h2ObjId)) {
                // 如果H2为null
                // 生成DSL语句，例如 Student.field = null;
                leftStatement = c1ClassName + "." + fieldName;
                String rightStatement = "null;";
                String dslStatement = genRefUpdateDslStatement(leftStatement, rightStatement);
                // 将该dsl语句加入函数体中
                dslMethodContentList.add(dslStatement);

                postProcessDslStatementNullAssignToObjFieldOrArrayIndex(leftStatement,
                        objId2objExpressionsMap,
                        dslObjFieldToObjIdMap);
            } else {
                // H2不为null
                // 生成DSL语句，例如 Student.field = dslStatement;
                leftStatement = c1ClassName + "." + fieldName;
                if (tryToGetDslExpressionOfObj(h2ObjId, objId2objExpressionsMap) == null) {
                    return;
                }
                String rightStatement = getDslExpressionOfObj(h2ObjId, objId2objExpressionsMap) + ";";
                String dslStatement = genRefUpdateDslStatement(leftStatement, rightStatement);
                // 将该dsl语句加入函数体中
                dslMethodContentList.add(dslStatement);

                // 更新两个数据结构 objId2objExpressionsMap 与 dslObjFieldToObjIdMap
                postProcessDslStatementAssignToObjFieldOrArrayIndex(leftStatement, h2ObjId,
                        objId2objExpressionsMap,
                        dslObjFieldToObjIdMap);
            }
        } else {
            // 修改的是实例字段
            // 生成DSL语句，例如 A.field = dslStatement;
            // 获得H1的id
            String h1ObjId = Utils.RegularExpressionProcess(putTraceLine, "H1:(.*?),");
            // 获得H1的type
            String h1Type = Utils.RegularExpressionProcess(putTraceLine, "C1:(.*?),");
            // 获得H2的id
            h2ObjId = Utils.RegularExpressionProcess(putTraceLine, "H2:(.*?),");
            // 获得修改H1的字段名
            String fieldName = Utils.RegularExpressionProcess(putTraceLine, "F:(.*?),");
            // 获得H1对象的dsl表示
            if (tryToGetDslExpressionOfObj(h1ObjId, objId2objExpressionsMap) == null) {
                return;
            }
            String h1DslExpression = getDslExpressionOfObj(h1ObjId, objId2objExpressionsMap);
            // 看看H2是否为NULL
            if ("NULL".equals(h2ObjId)) {
                // 如果H2为null
                leftStatement = h1DslExpression + "." + fieldName;
                String rightStatement = "null;";
                String dslStatement = genRefUpdateDslStatement(leftStatement, rightStatement);
                // 将该dsl语句加入函数体中
                dslMethodContentList.add(dslStatement);

                // 更新两个数据结构 objId2objExpressionsMap 与 dslObjFieldToObjIdMap
                postProcessDslStatementNullAssignToObjFieldOrArrayIndex(leftStatement,
                        objId2objExpressionsMap,
                        dslObjFieldToObjIdMap);
            } else {
                // H2不为null
                // objId2objExpressionsMap.get(h2ObjId)可能为null
                // 处理这种情况，下面的H2对象 用前未新建，可能是H1对象带来的
                // Put H1:0x000000000186c80e, C1:java/lang/String, IS:false, H2:0x000000000892731c, C2:[B, F:value, T:main, M:java/lang/String.<init> (Ljava/lang/String;)V
                if (tryToGetDslExpressionOfObj(h2ObjId, objId2objExpressionsMap) == null) {
                    return;
                }
                // 获得H2对象的dsl表示
                String h2DslExpression = getDslExpressionOfObj(h2ObjId, objId2objExpressionsMap);

                leftStatement = h1DslExpression + "." + fieldName;
                String rightStatement = h2DslExpression + ";";
                String dslStatement = genRefUpdateDslStatement(leftStatement, rightStatement);
                // 将该dsl语句加入函数体中
                dslMethodContentList.add(dslStatement);

                // 更新两个数据结构 objId2objExpressionsMap 与 dslObjFieldToObjIdMap
                postProcessDslStatementAssignToObjFieldOrArrayIndex(leftStatement, h2ObjId,
                        objId2objExpressionsMap,
                        dslObjFieldToObjIdMap);
            }

        }

    }


    /**
     * 处理PutA trace语句 赋值给array[index] trace转DSL
     * 生成 array[index] = dslStatement; DSL语句
     *
     * @param putATraceLine           PutA操作所在的Trace行
     * @param dslMethodContentList    生成的DSL程序的函数体
     * @param objId2objExpressionsMap 指定对象id在DSL程序中可以怎样表示出来 <objId, expressions>
     * @param dslObjFieldToObjIdMap   给定DSL语句（对象.field 或 对象数组[index]），看看该DSL语句指向哪个对象Id，主要是帮助处理Put与PutA的trace，减少查询时间
     */
    public static void genDslStatementAssignToArrayIndex(String putATraceLine,
                                                         List<String> dslMethodContentList,
                                                         Map<String, WhoPointToThisObjectCollection> objId2objExpressionsMap,
                                                         Map<String, String> dslObjFieldToObjIdMap) {
        // 修改数组index例子 PutA H1:0x0000000046cdf8bd, C1:[[Ljava/lang/invoke/LambdaForm$Name;, H2:0x000000000f0c8a99, C2:[Ljava/lang/invoke/LambdaForm$Name;, O:0, T:main, M:java/lang/invoke/LambdaForm.<clinit> ()V
        // 生成DSL语句，例如 array[index] = dslStatement;
        // 获得H1的id
        String h1ObjId = Utils.RegularExpressionProcess(putATraceLine, "H1:(.*?),");
        // 获得修改H1的index
        String index = Utils.RegularExpressionProcess(putATraceLine, "O:(.*?),");
        // 获得H1对象的dsl表示
        if (tryToGetDslExpressionOfObj(h1ObjId, objId2objExpressionsMap) == null) {
            return;
        }
        String h1DslExpression = getDslExpressionOfObj(h1ObjId, objId2objExpressionsMap);
        // 获得H2的id
        String h2ObjId = Utils.RegularExpressionProcess(putATraceLine, "H2:(.*?),");
        // H2可能为NULL
        if ("NULL".equals(h2ObjId)) {
            // H2为NULL
            // 修改数组index例子 PutA H1:0x0000000046cdf8bd, C1:[[Ljava/lang/invoke/LambdaForm$Name;, H2:NULL, C2:NULL, O:0, T:main, M:java/lang/invoke/LambdaForm.<clinit> ()V
            // 生成DSL语句，例如 array[index] = null;
            String leftStatement = h1DslExpression + "[" + index + "]";
            String rightStatement = "null;";
            String dslStatement = genRefUpdateDslStatement(leftStatement, rightStatement);
            // 将该dsl语句加入函数体中
            dslMethodContentList.add(dslStatement);

            // 更新两个数据结构 objId2objExpressionsMap 与 dslObjFieldToObjIdMap
            postProcessDslStatementNullAssignToObjFieldOrArrayIndex(leftStatement,
                    objId2objExpressionsMap,
                    dslObjFieldToObjIdMap);
        } else {
            // H2不为NULL
            // 获得H2对象的dsl表示
            if (tryToGetDslExpressionOfObj(h2ObjId, objId2objExpressionsMap) == null) {
                return;
            }
            String h2DslExpression = getDslExpressionOfObj(h2ObjId, objId2objExpressionsMap);

            // 生成DSL语句，例如 array[index] = dslStatement;
            String leftStatement = h1DslExpression + "[" + index + "]";
            String rightStatement = null;
            // 如果需要强制类型转换
            if (DslProgramGen.isCastType) {
                // 获得左边数组元素的类型
//                String equalSignLeftArrayType = objId2objExpressionsMap.get(h1ObjId).objectType;
                // 获得H1的type
                String equalSignLeftArrayType = Utils.RegularExpressionProcess(putATraceLine, "C1:(.*?),");
                // 获得低一个维度的type
                String oneDimLowerExpr = getOneDimLowerArrayExpr(equalSignLeftArrayType);
                // 强制类型转换
                rightStatement = "(" + oneDimLowerExpr + ")" + "(" + h2DslExpression + ")" + ";";
            } else {
                rightStatement = h2DslExpression + ";";
            }

            String dslStatement = genRefUpdateDslStatement(leftStatement, rightStatement);
            // 将该dsl语句加入函数体中
            dslMethodContentList.add(dslStatement);

            // 更新两个数据结构 objId2objExpressionsMap 与 dslObjFieldToObjIdMap
            postProcessDslStatementAssignToObjFieldOrArrayIndex(leftStatement, h2ObjId,
                    objId2objExpressionsMap,
                    dslObjFieldToObjIdMap);
        }

    }

    /**
     * 新增一个局部变量gc root，生成MOP语句添加到dslMethodContentList
     * @param objId 新增局部变量对象的id
     * @param objType 新增局部变量对象类型
     * @param dslMethodContentList 生成的DSL程序的函数体
     * @param objId2objExpressionsMap 指定对象id在DSL程序中可以怎样表示出来 <objId, expressions>
     * @param classTypeAndNumMap local root命名的辅助结构， 对于新建local root例如Student stu，如何命名stu，当前采用 "student"+num的方式表示
     */
    public static void genAddNewLocalRootDslStatement(String objId, String objType, List<String> dslMethodContentList,
                                                      Map<String, WhoPointToThisObjectCollection> objId2objExpressionsMap,
                                                      Map<String, Long> classTypeAndNumMap) {
        if (!"NULL".equals(objId)) { // 如果hId不为null， hId可能为null，比如 Student stu = null;，不处理这种情况
            // 生成DSL语句，例如 Student stu = dslStatement; 或 Student[][] stu = dslStatement;
            // 如果要创建local root，先获得local root的序号
            long prNum = getLocalRootNum(objType, classTypeAndNumMap);
            String leftStatement;
            String rightStatement;
            String prVariableName;
            // 判断local root是不是数组类型
            if (isArrayType(objType)) {
                // local root为数组类型
                // 获得数组elementType
                String elementType = getElementTypeFromArrayObjectType(objType);
                // 获得数组对象的维度
                int dimNum = getDimNumFromArrayObjectType(objType);
                // 组成local root的全名 小写(element类型)_array_prNum
                prVariableName = elementType.toLowerCase() + "_array_"+ dimNum + "_" + prNum;
                
                String squareBracket = "";
                for (int i = 0; i < dimNum; i++) {
                    squareBracket += "[]";
                }

                leftStatement = elementType + squareBracket + " " + prVariableName;
                if (DslProgramGen.isCastType) {
                    // 等号左右两边类型可能不匹配，比如等号右边为父类，等号左边为子类，进行强制类型转换
                    rightStatement = "(" + elementType + squareBracket + ")" + "(" + getDslExpressionOfObj(objId, objId2objExpressionsMap) + ")" + ";";
                } else {
                    rightStatement = getDslExpressionOfObj(objId, objId2objExpressionsMap) + ";";
                }

            } else {
                // local root为普通对象类型
                // 组成local root的全名 小写(类型)_prNum
                prVariableName = objType.toLowerCase() + "_" + prNum;

                leftStatement = objType + " " + prVariableName;

                rightStatement = getDslExpressionOfObj(objId, objId2objExpressionsMap) + ";";

                if (DslProgramGen.isCastType) {
                    // 等号左右两边类型可能不匹配，比如等号右边为父类，等号左边为子类，进行强制类型转换
                    rightStatement = "(" + objType + ")" + rightStatement;
                }
                // 判断 等号左边和右边类型是不是匹配的
                // 获得等号右边的类型
//                String objTypeOfRightStatment = objId2objExpressionsMap.get(objId).objectType;
//                if (!objType.equals(objTypeOfRightStatment)) {
//                    // 如果等号左右类型不匹配，进行强制转换
//
//                }
            }

            String dslStatement = leftStatement + " = " + rightStatement;
            // 将该dsl语句加入函数体中
            dslMethodContentList.add(dslStatement);
            // 将新建的local root添加到objId2objExpressionsMap
            if (objId2objExpressionsMap.get(objId) != null) {
                objId2objExpressionsMap.get(objId).lrAndPrPointToThisObjectList.add(prVariableName);
            }

        }
    }

    /**
     * 生成对局部变量gc root对象赋值为null的MOP语句
     * @param replaceObjId 局部变量对象id
     * @param dslMethodContentList 生成的DSL程序的函数体
     * @param objId2objExpressionsMap 指定对象id在DSL程序中可以怎样表示出来 <objId, expressions>
     */
    public static void genAssignNullToLocalRootDslStatement(String replaceObjId, List<String> dslMethodContentList,
                                                            Map<String, WhoPointToThisObjectCollection> objId2objExpressionsMap) {
        // 给replaceObjId局部变量赋值为null
        // 生成DSL语句，例如 stu = null;
        // R的内容就是之前local root指向的对象id，获得local root的dsl表示
        if (tryToGetDslExpressionOfObj(replaceObjId, objId2objExpressionsMap) == null) {
            return;
        }
        String leftStatement = getDslExpressionOfObj(replaceObjId, objId2objExpressionsMap);
        // 如果leftStatement是全局变量，不要给它赋值null
        if (leftStatement.contains("globalVar_")) {
            return;
        }
//        String leftStatement = objId2objExpressionsMap.get(replaceObjId).lrAndPrPointToThisObjectList.get(0);
        String rightStatement = "null;";
        String dslStatement = leftStatement + " = " + rightStatement;
        // 将该dsl语句加入函数体中
        dslMethodContentList.add(dslStatement);

        // 从谁指向R的local root列表中移除leftStatement
        objId2objExpressionsMap.get(replaceObjId).lrAndPrPointToThisObjectList.remove(0);
    }

    /**
     * 处理Add LR trace语句 赋值给local root trace转DSL
     * 生成 Student stu = dslStatement; 或 stu = dslStatement; 或 Student[][] stu = dslStatement DSL语句
     *
     * @param addLrTraceLine          addLrTraceLine操作所在的Trace行
     * @param dslMethodContentList    生成的DSL程序的函数体
     * @param objId2objExpressionsMap 指定对象id在DSL程序中可以怎样表示出来 <objId, expressions>
     * @param classTypeAndNumMap      local root命名的辅助结构， 对于新建local root例如Student stu，如何命名stu，当前采用 "student"+num的方式表示
     */
    public static void genDslStatementAssignToLocalRoot(String addLrTraceLine,
                                                        List<String> dslMethodContentList,
                                                        Map<String, WhoPointToThisObjectCollection> objId2objExpressionsMap,
                                                        Map<String, Long> classTypeAndNumMap) {
        // 新建local root例子 Add LR H:0x000000004edde6e5, C:java/lang/ThreadGroup, T:main, R: NULL, M:java/lang/ThreadGroup.addUnstarted ()V
        // 给local root赋值例子 Add LR H:0x000000000d716361, C:java/lang/Class, T:main, R:0x000000004459eb14, M:java/util/ImmutableCollections$MapN.<init> ([Ljava/lang/Object;)V

        // 首先获得R部分内容
        String contentOfR = Utils.RegularExpressionProcess(addLrTraceLine, "R: ?(.*?),");
        // 获得H的内容
        String hId = Utils.RegularExpressionProcess(addLrTraceLine, "H:(.*?),");
        // 获得类型
        String lrType = Utils.RegularExpressionProcess(addLrTraceLine, "C:(.*?),");
        lrType = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(lrType);

        // 有些对象存在使用前未新建的情况，忽略这行trace
        if (tryToGetDslExpressionOfObj(hId, objId2objExpressionsMap) == null && !("NULL".equals(hId))) {
            return;
        }
        if (contentOfR.equals("NULL")) { // 表示新增一个gc root
            genAddNewLocalRootDslStatement(hId, lrType, dslMethodContentList,
                    objId2objExpressionsMap,
                    classTypeAndNumMap);

        } else { // 表示修改一个gc root
            // hId可能为NULL
            if ("NULL".equals(hId)) {
                // hId为null
                // 生成DSL语句，例如 stu = null;
                // R的内容就是之前local root指向的对象id，获得local root的dsl表示
                genAssignNullToLocalRootDslStatement(contentOfR, dslMethodContentList,
                        objId2objExpressionsMap);
            } else {
                // hId不为null
                // 获得replace值的类型，判断replace值类型与新值类型是否一致
                if (objId2objExpressionsMap.get(contentOfR) == null) {
                    // replace值在局部变量表中找不到，只生成新值的局部变量
                    // 对于新值，定义一个新的局部变量，例如 Student stu = stu1;
                    genAddNewLocalRootDslStatement(hId, lrType, dslMethodContentList,
                            objId2objExpressionsMap,
                            classTypeAndNumMap);
                    return;
                }
                String replaceObjType = objId2objExpressionsMap.get(contentOfR).objectType;
                // 若新值和replace值类型相同
                if (lrType.equals(replaceObjType)) {
                    // 生成DSL语句，例如 stu = stu1;
                    // R的内容就是之前local root指向的对象id，获得local root的dsl表示
                    String leftStatement = objId2objExpressionsMap.get(contentOfR).lrAndPrPointToThisObjectList.get(0);
                    String rightStatement = getDslExpressionOfObj(hId, objId2objExpressionsMap);

                    if (DslProgramGen.isCastType) {
                        // 获得左表达式的类型
                        String leftObjType = objId2objExpressionsMap.get(contentOfR).objectType;
                        if (isArrayType(leftObjType)) {
                            leftObjType = castArraySignaturToArrayExpr(leftObjType);
                        }
                        // 等号左右两边类型可能不匹配，比如等号右边为父类，等号左边为子类，进行强制类型转换
                        rightStatement = "(" + leftObjType + ")" + "(" +rightStatement + ")";
                    }
                    rightStatement += ";";
                    String dslStatement = leftStatement + " = " + rightStatement;
                    // 将该dsl语句加入函数体中
                    dslMethodContentList.add(dslStatement);

                    if (objId2objExpressionsMap.get(hId) != null) {
                        // 将local root新指向的对象添加到objId2objExpressionsMap
                        objId2objExpressionsMap.get(hId).lrAndPrPointToThisObjectList.add(leftStatement);
                    }
                    if (objId2objExpressionsMap.get(contentOfR) != null) {
                        // 从谁指向R的local root列表中移除leftStatement
                        objId2objExpressionsMap.get(contentOfR).lrAndPrPointToThisObjectList.remove(0);
                    }

                } else {
                    // 新值和replace值的类型不同，产生两条MOP语句
                    // 对于新值，定义一个新的局部变量，例如 Student stu = stu1;
                    genAddNewLocalRootDslStatement(hId, lrType, dslMethodContentList,
                            objId2objExpressionsMap,
                            classTypeAndNumMap);
                    // 对于replace值，为其赋值为null，例如 stu = null;
                    genAssignNullToLocalRootDslStatement(contentOfR, dslMethodContentList,
                            objId2objExpressionsMap);
                }

            }
        }
    }

    /**
     * 在生成 A.field = dslStatement; 或 array[index] = dslStatement; DSL语句之后
     * 更新两个数据结构 objId2objExpressionsMap 与 dslObjFieldToObjIdMap
     *
     * @param leftStatement           用DSL语句表示的等号左边内容
     * @param pointToObjectId         leftStatement新指向对象id
     * @param objId2objExpressionsMap 指定对象id在DSL程序中可以怎样表示出来 <objId, expressions>
     * @param dslObjFieldToObjIdMap   给定DSL语句（对象.field 或 对象数组[index]），看看该DSL语句指向哪个对象Id，主要是帮助处理Put与PutA的trace，减少查询时间
     */
    public static void postProcessDslStatementAssignToObjFieldOrArrayIndex(String leftStatement, String pointToObjectId,
                                                                           Map<String, WhoPointToThisObjectCollection> objId2objExpressionsMap,
                                                                           Map<String, String> dslObjFieldToObjIdMap) {
        // 更新两个数据结构 objId2objExpressionsMap 与 dslObjFieldToObjIdMap
        // step 1. 更新objId2objExpressionsMap，增加谁指向该pointToObject
        if (objId2objExpressionsMap.get(pointToObjectId) == null) {
            objId2objExpressionsMap.put(pointToObjectId, new WhoPointToThisObjectCollection("thisObjFromSubMethod", pointToObjectId));
        }
        objId2objExpressionsMap.get(pointToObjectId).fieldOfObjExpressionsPointToThisObjectList.add(leftStatement);



        // step 2. 若A.field或array[index]之前指向对象b，修改objId2objExpressionsMap，删除谁指向对象b的DSL语句中 A.field或array[index]
        // A.field或array[index]之前指向对象b的id
        String prePointObjId = dslObjFieldToObjIdMap.get(leftStatement);
        if (prePointObjId != null) {
            // 移除谁指向b的DSL语句中 A.field或array[index]
            objId2objExpressionsMap.get(prePointObjId).fieldOfObjExpressionsPointToThisObjectList.remove(leftStatement);
        }
        // step 3.修改dslObjFieldToObjIdMap，A.field原来指向对象b，现在指向新建对象
        dslObjFieldToObjIdMap.put(leftStatement, pointToObjectId);
    }


    /**
     * 在生成 A.field = null; 或 array[index] = null; DSL语句之后
     * 更新两个数据结构 objId2objExpressionsMap 与 dslObjFieldToObjIdMap
     *
     * @param leftStatement           用DSL语句表示的等号左边内容
     * @param objId2objExpressionsMap 指定对象id在DSL程序中可以怎样表示出来 <objId, expressions>
     * @param dslObjFieldToObjIdMap   给定DSL语句（对象.field 或 对象数组[index]），看看该DSL语句指向哪个对象Id，主要是帮助处理Put与PutA的trace，减少查询时间
     */
    public static void postProcessDslStatementNullAssignToObjFieldOrArrayIndex(String leftStatement,
                                                                               Map<String, WhoPointToThisObjectCollection> objId2objExpressionsMap,
                                                                               Map<String, String> dslObjFieldToObjIdMap) {
        // 更新两个数据结构 objId2objExpressionsMap 与 dslObjFieldToObjIdMap
        // step 1. 若A.field或array[index]之前指向对象b，修改objId2objExpressionsMap，删除谁指向对象b的DSL语句中 A.field或array[index]
        // A.field或array[index]之前指向对象b的id
        String prePointObjId = dslObjFieldToObjIdMap.get(leftStatement);
        if (prePointObjId != null) {
            // 移除谁指向b的DSL语句中 A.field或array[index]
            objId2objExpressionsMap.get(prePointObjId).fieldOfObjExpressionsPointToThisObjectList.remove(leftStatement);
        }
        // step 2.修改dslObjFieldToObjIdMap，A.field原来指向对象b，现在指向null
        dslObjFieldToObjIdMap.put(leftStatement, null);
    }
}
